In [ ]:
# Load all analyzers
import graph_analyzer
tickers = ['ANC', 'DGC', 'FTC', 'GLD', 'LKY', 'MNC', 'NMC', 'NVC', 'PPC', 'LTC', 'DRK', 'MEC']
analyzers = map(graph_analyzer.GraphAnalyzer, tickers)
In [92]:
import mining
mining_analyzers = map(mining.MiningAnalyzer, analyzers)
In [120]:
# Compute concentration (per capita % of coins) over time for each coin
concentrations = []
for azr in analyzers:
# Generate powers-of-10 tx_ids, e.g., [10, 100, 1000, ...]
tx_ids = [10 ** i for i in range(1, int(log(azr.now_tx_id, 10)) + 1)] + [azr.now_tx_id]
counts = []
for tx_id in tx_ids:
# Compute mean balance / total balance to get distribution of existing wealth
mean_balance = azr.mean_balance_for_cluster(tx_id=tx_id)
total_balance = azr.balance_for_blockchain(tx_id=tx_id)
if total_balance == 0:
counts.append(None)
else:
pct = mean_balance / float(total_balance)
counts.append(pct)
concentrations.append((tx_ids, counts))
In [143]:
# Plot on log scale
colors = [
'#e50554',
'#07ec00',
'#0266c8',
'#804a2d',
'#c5e3bf',
'#003bba',
'#f90000',
'#00ffb8',
'#ff8737',
'#a054e1',
'#8f5a38',
'#2f1e1e'
]
for i, (x, y) in enumerate(concentrations):
now_tx_id = analyzers[i].now_tx_id
xs = [float(n) / now_tx_id for n in x]
ys = y
plt.semilogy(xs, ys, label=analyzers[i].ticker.upper(), color=colors[i % len(colors)])
plt.ylabel('% of Wealth Held Per Capita')
plt.xlabel('% of Transactions To-Date')
plt.title('% of Wealth Held Per Capita Over Time')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
Out[143]:
In [78]:
# Let's look at early mining, i.e., the first 1000 blocks
num_miners = []
num_entities = []
first_n = 1000
for (azr, mining_azr) in zip(analyzers, mining_analyzers):
tx_id = 5000
miner_pubkeys = mining_azr.miner_pubkeys(tx_id=tx_id)
while len(miner_pubkeys) < first_n:
tx_id *= 2
miner_pubkeys = mining_azr.miner_pubkeys(tx_id=tx_id)
miner_pubkeys = miner_pubkeys[:first_n]
distinct_miners = set(miner_pubkeys)
distinct_entities = set(azr.cluster_for_pubkey(pk) for pk in distinct_miners)
num_miners.append(len(distinct_miners))
num_entities.append(len(distinct_entities))
In [79]:
xs = [market.rank_for_ticker(azr.ticker) for azr in analyzers]
ys = num_entities
plot_with_best_fit(xs, ys, title='# Distinct Miners in First 1000 Blocks vs. Market Cap', ylabel='# Distinct Miners', xlabel='Market Cap (Ranking)')
In [121]:
# Now lets look at the average number of blocks mined per entity
data = []
block_nums = [1, 10, 100, 500, 1000, 5000, 10000, 20000, 50000, 100000]
for (azr, mining_azr) in zip(analyzers, mining_analyzers):
miner_pubkeys = mining_azr.miner_pubkeys()
num_entities = []
keys = set([])
entities = set([])
prev_n = 0
block_nums_for_azr = block_nums + [azr.now_tx_id]
for n in block_nums_for_azr:
new_keys = set(miner_pubkeys[prev_n:n]).difference(keys)
new_entities = set(azr.cluster_for_pubkey(pk) for pk in new_keys)
keys.update(new_keys)
distinct_entities.update(new_entities)
num_entities.append(len(distinct_entities))
prev_n = n
data.append(num_entities)
In [121]:
# This is the average number of blocks mined per miner
for i, series in enumerate(data):
series_scaled = []
xs = block_nums
print xs
for j, n in enumerate(series[:-1]):
series_scaled.append(float(xs[j]) / n)
plt.figure(i)
plt.plot(xs, series_scaled)
plt.title(analyzers[i].ticker)
In [39]:
import operator
from math import log
from collections import Counter
from scipy.stats import linregress
import market
In [10]:
def plot_with_best_fit(xs, ys, func=plt.plot, color='r', ylabel=None, xlabel=None, title=None):
"""Plot data with a line of best fit."""
coeffs = linregress(xs, ys)
best_fit_xs = [min(xs), max(xs)]
best_fit_ys = [coeffs[0] * x + coeffs[1] for x in best_fit_xs]
# Add title and labels
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
# Plot data
func(xs, ys, color + 'o', best_fit_xs, best_fit_ys, color + '--')
print 'Correlation coefficient: %.3f' % coeffs[2]
In [146]:
# Calculate (# public keys / # clusters), i.e., average keys per entity
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
ys = [len(azr.balances) / float(len(azr.clusters)) for azr in analyzers]
plot_with_best_fit(xs, ys, title='# Keys per Entity vs. Market Cap', ylabel='Avg. # Keys', xlabel='Log(Market Cap)')
In [248]:
top_n = 10
lengths = [[len(azr.clusters[c]) for c in azr.clusters] for azr in analyzers]
ys = [sum(sorted(z, reverse=True)[:top_n]) / float(len(analyzers[i].balances)) for i, z in enumerate(zs)]
# Calculate (# public keys / # clusters), i.e., average keys per entity
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
plot_with_best_fit(xs, ys, title='Keys Covered By Top 10 Clusters vs. Market Cap', ylabel='Pct. of Keys', xlabel='Log(Market Cap)')
In [247]:
lengths = [len([cluster for cluster in azr.clusters if len(azr.clusters[cluster]) == 1]) for azr in analyzers]
ys = [float(length) / len(azr.clusters) for (length, azr) in zip(lengths, analyzers)]
# Calculate (# public keys / # clusters), i.e., average keys per entity
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
plot_with_best_fit(xs, ys, title='Single-Key Clusters vs. Market Cap', ylabel='Proportion of Single-Key Clusters', xlabel='Log(Market Cap)')
In [113]:
# Compute wealth concentration by 10 richest individuals
top_n = 10
pcts = []
for azr in analyzers:
richest = azr.richest_n_clusters(top_n)
total_held_by_richest = sum(zip(*richest)[1])
total_in_blockchain = azr.balance_for_blockchain()
pct = total_held_by_richest / float(total_in_blockchain)
pcts.append(pct)
In [86]:
# Plot wealth concentration vs. market cap ranking
xs = [market.rank_for_ticker(azr.ticker) for azr in analyzers]
ys = pcts
plot_with_best_fit(xs, ys, title='Wealth Held by %d Richest Entities vs. Market Cap' % top_n, ylabel='Proportion of Wealth', xlabel='Market Cap (Ranking)')
In [116]:
# Plot wealth concentration vs. raw market cap (on log scale)
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
ys = pcts
plot_with_best_fit(xs, ys, title='Wealth Held by %d Richest Entities vs. Log(Market Cap)' % top_n, ylabel='Proportion of Wealth', xlabel='Log(Market Cap)')
In [90]:
# Next, look at % of blocks mined by top n miners
def pct_mined_by_top_n(azr, top_n):
miner_pubkeys = azr.miner_pubkeys()
total_blocks_mined = len(miner_pubkeys)
counter = Counter(miner_pubkeys)
top_miners = counter.most_common(top_n)
total_by_top_n = sum([blocks for (_, blocks) in top_miners])
pct = total_by_top_n / float(total_blocks_mined)
return pct
In [249]:
# Start by looking at top 10 miners
top_n = 10
pcts_mined = map(lambda azr: pct_mined_by_top_n(azr, top_n), mining_analyzers)
# Plot mining percentages vs. market cap ranking
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
ys = pcts_mined
plot_with_best_fit(xs, ys, color='b', title='Blocks Mined by %d Best Miners vs. Log(Market Cap)' % top_n, ylabel='Proportion of Blocks', xlabel='Log(Market Cap)')
In [250]:
# Let's do the same thing for the top 1 miner
top_n = 1
pcts_mined = map(lambda azr: pct_mined_by_top_n(azr, top_n), mining_analyzers)
# Plot mining percentages vs. market cap ranking
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
ys = pcts_mined
plot_with_best_fit(xs, ys, color='b', title='Blocks Mined by %d Best Miners vs. Market Cap' % top_n, ylabel='Proportion of Blocks', xlabel='Market Cap (Ranking)')
In [103]:
def richest_n_pubkeys(azr, n):
balances = {
pubkey: azr.balances[pubkey][-1][1] for pubkey in azr.balances
}
richest_n = sorted(balances.items(), key=operator.itemgetter(1), reverse=True)[:n]
return richest_n
In [105]:
# Compute wealth concentration by 10 richest individuals
top_n = 10
pcts = []
for azr in analyzers:
richest = richest_n_pubkeys(azr, top_n)
total_held_by_richest = sum(zip(*richest)[1])
total_in_blockchain = azr.balance_for_blockchain()
pct = total_held_by_richest / float(total_in_blockchain)
pcts.append(pct)
In [112]:
# Plot wealth concentration vs. market cap ranking
xs = [log(market.cap_for_ticker(azr.ticker), 10) for azr in analyzers]
ys = pcts
plot_with_best_fit(xs, ys, title='Wealth Held by %d Richest Addresses vs. Log(Market Cap)' % top_n, ylabel='Proportion of Wealth', xlabel='Log(Market Cap)')
In [ ]: